//
//  HykNetworkTool.swift
//  sinaWeiBo
//
//  Created by hyk on 15/11/26.
//  Copyright © 2015年 hyk. All rights reserved.
//

import UIKit

import AFNetworking

// 网络请求的枚举
enum HykNetoworkMethod: String {
    case GET = "GET"
    case POST = "POST"
    
}
/// 统一管理错误
enum HykNetworkToolError:Int{
    case EmptyAccessToken = -1
    case EmptyUid = -2
    
    //属性，根据不同的枚举类型返回不同的值
    var description:String{
        switch self {
        case EmptyAccessToken:
            return "AccessToken没有值"
        case EmptyUid:
            return "EmptyUid没有值"
        
        }
    }
    // 方法, 根据当前类型返回一个NSError
    func error() ->NSError {
        
        // domain: 错误类型: 自定义
        // code: 错误代码: 自定义,负数
        // userInfo: 附加信息, 错误的描述
        
      return NSError(domain: "cn.itcast.error.net", code: self.rawValue, userInfo: ["description": self.description])
    }

}
//网络单例
class HykNetworkTool: AFHTTPSessionManager {

    //单例
    static let shardInstance:HykNetworkTool = {
    //baseURL
        
        let baseURL = NSURL(string: "https://api.weibo.com/")
        let tool = HykNetworkTool(baseURL: baseURL)
        
//        发现服务器会报错,不支持text/pain类型,因为AFN没有支持,需要手动添加
//        在 NetworkTools 中增加反序列化数据格式
        // 添加响应的序列化器
        tool.responseSerializer.acceptableContentTypes?.insert("text/plain")

    return tool
    }()
    
    
    //MARK: - Oauth授权
    ///申请应用是分配的AppKey
    private let client_id = "3783704283"
    
    //授权回调地址 、一定要一样跟你的应用
    let redirect_uri = "http://www.baidu.com/"
    
    /// 申请应用时分配的AppSecret
    private let client_secret = "2a292e7a50ad5e83313ec16261551606"
    ///返回授权界面的URL地址
    func oauthURL() ->NSURL {
       //使用GET方式拼接登录界面请求地址
        let urlString = "https://api.weibo.com/oauth2/authorize?client_id=\(client_id)&redirect_uri=\(redirect_uri)"
        
        return NSURL(string:urlString)!
    
    }
    
     // MARK: - 加载Access Token ，添加一个 闭包参数, 当网络成功或失败时调用这个闭包通知调用者
    func loadAccessToken(code: String,finished: NetworkCallback){
      //api地址
        let urlString = "https://api.weibo.com/oauth2/access_token"
        
        //POST 参数
        let parameters = [
            "client_id": client_id,
            "client_secret": client_secret,
            "grant_type": "authorization_code",
            "code": code,
            "redirect_uri": redirect_uri
        
        ]
        request(requestMethod: HykNetoworkMethod.POST, urlString: urlString, parameters: parameters, needAccessToken: false, finished: finished)
//        POST(urlString, parameters: parameters, success: { (_, result) -> Void in
//                print("result:\(result)")
//            finish(result: result as? [String : AnyObject],error:nil)
//            }) { (_, error) -> Void in
//                print("error:\(error)")
//                finish(result: nil, error: error)
//             
//        }
    
    
    }
    // MARK: - 获取用户数据
    func loadUserInfo(finished: NetworkCallback) {
        //        guard let access_token = CZUserAccount.loadUserAccount()?.access_token else {
        //            print("access_token 没有值")
        //
        //            let error = CZNetworkToolError.EmptyAccessToken.error()
        //
        //            finished(result: nil, error: error)
        //            return
        //        }
        
        guard let uid = HykUserAccount.loadUserAccount()?.uid else {
            print("uid没有值")
            let error = HykNetworkToolError.EmptyUid.error()
            finished(result: nil, error: error)
            return
        }
        
        let urlString = "2/users/show.json"
        
        // 参数
        let parameters = [
            "uid": uid
        ]
        
        // 发送请求 网络工具类只负责加载数据,不处理数据,交给别人处理
        request(requestMethod: HykNetoworkMethod.GET, urlString: urlString, parameters: parameters, needAccessToken: true, finished: finished)
        

//        GET(urlString, parameters: parameters, success: { (_, result) -> Void in
////            print("请求用户数据成功:\(result)")
//            finished(result: result as?  [String:AnyObject], error: nil )
//            }) { (_, error) -> Void in
////                print("获取用户信息失败:\(error)")
//                finished(result: nil, error: error )
//        }
    
    
    }
    
    // MARK: - 加载微博数据
    func loadStatus(finished: NetworkCallback) {   // 通过闭包告诉调用者网络请求成功还是失败
        //        guard let access_token = CZUserAccount.loadUserAccount()?.access_token else {
        //            print("access_token 没有值")
        //            let error = CZNetworkToolError.EmptyAccessToken.error()
        //
        //            finished(result: nil, error: error)
        //            return
        //        }
        
        // url
        let urlString = "https://api.weibo.com/2/statuses/home_timeline.json"
        
        // 参数
        let parameters = [String: AnyObject]()
        
        // 调用封装好的GET请求
        
        let debug = false
        if debug{
           //加载本地数据
            loadLocalStatuses(finished)
        }else{
        
          //加载网络数据
            request(requestMethod: HykNetoworkMethod.GET, urlString: urlString, parameters: parameters, needAccessToken: true, finished: finished)
        }
        
        //        requestGET(urlString, parameters: parameters, finished: finished)
        //        GET(urlString, parameters: parameters, success: { (_, result) -> Void in
        //            finished(result: result as! [String : AnyObject], error: nil)
        //            }) { (_, error) -> Void in
        //                finished(result: nil, error: error)
        //        }
    }
    
    /// 将本地的测试微博数据加载进来
    private func loadLocalStatuses(finished: NetworkCallback){
    //获取本地路径
        let path = NSBundle.mainBundle().pathForResource("statuses", ofType: "json")!
        
        // 从文件加载数据 NSData
        let data = NSData(contentsOfFile: path)!
    
        // 将 NSData 转成 JSON
        // throws 有异常,需要处理异常
        // try! 强制try, 如果JSONObjectWithData出现异常,程序直接崩溃
        //        let json = try! NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions(rawValue: 0))
        
        do{
            let json = try?NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions(rawValue: 0))
            // 通知调用者获取到了本地数据
            finished(result: json as? [String:AnyObject], error: nil)
        }catch{
           print("出现异常")
        }
    
    
    
    }
    
    //自定义闭包
    typealias NetworkCallback = (result:[String:AnyObject]?,error:NSError?) ->()
    /**
    抽取AFN GET / POST 方法,网络请求的统一入口都是这个方法
    
    - parameter requestMethod: 请求方式
    - parameter urlString:     url地址
    - parameter parameters:    参数
    - parameter finished:      回调的闭包
    */

    func request(requestMethod requestMethod: HykNetoworkMethod, urlString: String, var parameters: [String: AnyObject], needAccessToken: Bool, finished: NetworkCallback) {
        
        // 需要accessToken,就拼接
        if needAccessToken {
            // 判断 access_token是否存在,存在就拼接,不存在就告诉调用者access_token 为空
            guard let access_token = HykUserAccount.loadUserAccount()?.access_token else {
                print("access_token 没有值")
                
                let error = HykNetworkToolError.EmptyAccessToken.error()
                
                finished(result: nil, error: error)
                return
            }
            
            // 在参数里面拼接 access_token
            parameters["access_token"] = access_token
        }
        
        // 准备成功的闭包, 在外面只要准备一次,可以传给GET,也可以传给POST
        let successCallback = { (task: NSURLSessionDataTask, result: AnyObject) -> Void in
            // 执行的代码
            finished(result: result as? [String : AnyObject], error: nil)
        }
        
        // 准备失败的闭包
        let failureCallback = { (task: NSURLSessionDataTask?, error: NSError) -> Void in
            finished(result: nil, error: error)
        }
    
        // 根据请求方式,发送对应的请求
        switch requestMethod {
            
        case .GET:
            GET(urlString, parameters: parameters, success: successCallback, failure: failureCallback)
        case .POST:
            POST(urlString, parameters: parameters, success: successCallback, failure: failureCallback)

        }
    }

    
}
